<!DOCTYPE html><html lang="zh-Hans"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><meta name="description" content="js各种知识"><meta name="keywords" content="js other"><meta name="author" content="晟松"><meta name="copyright" content="晟松"><title>js各种知识 | 晟松</title><link rel="shortcut icon" href="/logo.png"><link rel="stylesheet" href="/css/index.css?version=1.9.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@latest/css/font-awesome.min.css?version=1.9.0"><meta name="format-detection" content="telephone=no"><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="dns-prefetch" href="https://hm.baidu.com"><script>var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?c34d81d53341febe06a155941e2df16d";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();</script><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><script>var GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容:${query}"}},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  hexoVersion: '5.4.0'
} </script><meta name="generator" content="Hexo 5.4.0"></head><body><i class="fa fa-arrow-right" id="toggle-sidebar" aria-hidden="true"></i><div id="sidebar" data-display="true"><div class="toggle-sidebar-info text-center"><span data-toggle="切换文章详情">切换站点概览</span><hr></div><div class="sidebar-toc"><div class="sidebar-toc__title">目录</div><div class="sidebar-toc__progress"><span class="progress-notice">你已经读了</span><span class="progress-num">0</span><span class="progress-percentage">%</span><div class="sidebar-toc__progress-bar"></div></div><div class="sidebar-toc__content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%90%84%E7%A7%8D%E6%9D%82%E4%B9%B1%E7%9F%A5%E8%AF%86%E7%82%B9"><span class="toc-number">1.</span> <span class="toc-text">各种杂乱知识点</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%8F%98%E9%87%8F%E6%8F%90%E5%8D%87"><span class="toc-number">1.1.</span> <span class="toc-text">1.变量提升</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E5%A0%86%E6%A0%88%EF%BC%8C%E6%B7%B1%E6%8B%B7%E8%B4%9D%EF%BC%8C%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">1.2.</span> <span class="toc-text">2.堆栈，深拷贝，浅拷贝</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-%E5%90%84%E7%A7%8D%E9%81%87%E8%A7%81%E7%9A%84%E5%B0%8F%E6%8A%80%E5%B7%A7"><span class="toc-number">1.3.</span> <span class="toc-text">3.各种遇见的小技巧</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%96%E5%BE%97%E4%B8%A4%E4%B8%AA%E5%80%BC%E7%9A%84%E4%B8%AD%E9%97%B4%E5%80%BC"><span class="toc-number">1.3.1.</span> <span class="toc-text">取得两个值的中间值</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%9A%84%E7%94%9F%E6%88%90"><span class="toc-number">1.3.2.</span> <span class="toc-text">随机数的生成</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#koa-class%E5%86%99controller"><span class="toc-number">1.3.3.</span> <span class="toc-text">koa class写controller</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#object%E5%8E%9F%E5%9E%8B%E5%88%A4%E6%96%AD%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B"><span class="toc-number">1.3.4.</span> <span class="toc-text">object原型判断数据类型</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-%E5%90%84%E7%A7%8D%E5%B0%8F%E7%9F%A5%E8%AF%86%E7%82%B9"><span class="toc-number">1.4.</span> <span class="toc-text">4.各种小知识点</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1%EF%BC%9ACommonJS-%E8%A7%84%E8%8C%83%E6%80%BB%E7%BB%93%E4%B8%8E%E6%89%A9%E5%B1%95"><span class="toc-number">1.4.1.</span> <span class="toc-text">1：CommonJS 规范总结与扩展</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2%EF%BC%9AES6%E7%9A%84class%E4%BD%BF%E7%94%A8"><span class="toc-number">1.4.2.</span> <span class="toc-text">2：ES6的class使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3%EF%BC%9Ajs%E5%8D%95%E7%BA%BF%E7%A8%8B%E5%92%8C%E5%BC%82%E6%AD%A5"><span class="toc-number">1.4.3.</span> <span class="toc-text">3：js单线程和异步</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4%EF%BC%9Ajs%E5%AF%B9%E8%B1%A1%E6%96%B9%E6%B3%95"><span class="toc-number">1.4.4.</span> <span class="toc-text">4：js对象方法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5%EF%BC%9Aformdata%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="toc-number">1.4.5.</span> <span class="toc-text">5：formdata文件上传</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6%EF%BC%9A%E6%B5%8F%E8%A7%88%E5%99%A8console-log"><span class="toc-number">1.4.6.</span> <span class="toc-text">6：浏览器console.log</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7%EF%BC%9Acss%E7%9A%84-important"><span class="toc-number">1.4.7.</span> <span class="toc-text">7：css的 !important</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8%EF%BC%9Acss%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7"><span class="toc-number">1.4.8.</span> <span class="toc-text">8：css自定义属性</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9%EF%BC%9Avue%E5%8A%A8%E6%80%81%E7%BB%91%E5%AE%9A%E6%A0%B7%E5%BC%8F%E7%9A%84bug"><span class="toc-number">1.4.9.</span> <span class="toc-text">9：vue动态绑定样式的bug</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10%EF%BC%9Avue%E9%A1%B9%E7%9B%AEeslint%E5%92%8C%E6%9C%AC%E5%9C%B0%E5%86%B2%E7%AA%81"><span class="toc-number">1.4.10.</span> <span class="toc-text">10：vue项目eslint和本地冲突</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#11%EF%BC%9AsetTimeout-func-4-7"><span class="toc-number">1.4.11.</span> <span class="toc-text">11：setTimeout(func,4.7)</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#12%EF%BC%9Ajs%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF%E5%8E%9F%E7%90%86"><span class="toc-number">1.4.12.</span> <span class="toc-text">12：js事件循环原理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#13%EF%BC%9Avue-router%E7%9A%84%E7%89%B9%E6%AE%8A%E7%94%A8%E6%B3%95"><span class="toc-number">1.4.13.</span> <span class="toc-text">13：vue-router的特殊用法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#14%EF%BC%9Av-for%E5%92%8Cv-if%E4%B8%8D%E8%83%BD%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8"><span class="toc-number">1.4.14.</span> <span class="toc-text">14：v-for和v-if不能同时使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#15%EF%BC%9A%E4%B8%80%E9%81%93%E7%89%B9%E6%AE%8A%E7%9A%84js%E9%A2%98-%E8%BF%9E%E7%AD%89"><span class="toc-number">1.4.15.</span> <span class="toc-text">15：一道特殊的js题-连等</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#16%EF%BC%9A%E4%BA%8B%E4%BB%B6%E4%BB%A3%E7%90%86"><span class="toc-number">1.4.16.</span> <span class="toc-text">16：事件代理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#17%EF%BC%9Avue-router%E7%9A%84history%E5%8E%9F%E7%94%9Fapi"><span class="toc-number">1.4.17.</span> <span class="toc-text">17：vue-router的history原生api</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#18%EF%BC%9Apostcss%E5%92%8Cscss%E7%AD%89%E5%8C%BA%E5%88%AB"><span class="toc-number">1.4.18.</span> <span class="toc-text">18：postcss和scss等区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#19%EF%BC%9Apromise-resolve-reject%E5%90%8E%E7%9A%84%E4%BB%A3%E7%A0%81%E4%B9%9F%E4%BC%9A%E8%BF%90%E8%A1%8C"><span class="toc-number">1.4.19.</span> <span class="toc-text">19：promise resolve&#x2F;reject后的代码也会运行</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#20%EF%BC%9A%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%87%8C%E7%9A%84function"><span class="toc-number">1.4.20.</span> <span class="toc-text">20：块级作用域里的function</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#21%EF%BC%9A%E4%BD%BF%E7%94%A8%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84style%E7%9A%84%E7%89%B9%E5%AE%9A%E5%B1%9E%E6%80%A7%E5%88%A4%E6%96%AD%E6%B5%8F%E8%A7%88%E5%99%A8%E5%9E%8B%E5%8F%B7"><span class="toc-number">1.4.21.</span> <span class="toc-text">21：使用浏览器的style的特定属性判断浏览器型号</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#22%EF%BC%9Acss%E7%94%BB%E6%89%87%E5%BD%A2"><span class="toc-number">1.4.22.</span> <span class="toc-text">22：css画扇形</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#23%EF%BC%9Anode%E4%B8%AD%E4%BD%BF%E7%94%A8import"><span class="toc-number">1.4.23.</span> <span class="toc-text">23：node中使用import</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#24%EF%BC%9Ajs%E5%AF%B9%E8%B1%A1%E7%9A%84for-in%E9%A1%BA%E5%BA%8F"><span class="toc-number">1.4.24.</span> <span class="toc-text">24：js对象的for in顺序</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#25%EF%BC%9Aa%E2%80%93%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-number">1.4.25.</span> <span class="toc-text">25：a–的问题</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B9%A6%E7%B1%8D"><span class="toc-number">2.</span> <span class="toc-text">书籍</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#js%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%EF%BC%88%E7%AC%AC%E5%9B%9B%E7%89%88%EF%BC%89"><span class="toc-number">2.1.</span> <span class="toc-text">js高级程序设计（第四版）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%A0%E6%89%80%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84js%E2%80%93%E4%B8%8A"><span class="toc-number">2.2.</span> <span class="toc-text">你所不知道的js–上</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%A0%E6%89%80%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84js%E2%80%93%E4%B8%AD"><span class="toc-number">2.3.</span> <span class="toc-text">你所不知道的js–中</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%A0%E6%89%80%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84js%E2%80%93%E4%B8%8B"><span class="toc-number">2.4.</span> <span class="toc-text">你所不知道的js–下</span></a></li></ol></li></ol></div></div><div class="author-info hide"><div class="author-info__avatar text-center"><img src="/img/avatar.png"></div><div class="author-info__name text-center">晟松</div><div class="author-info__description text-center">晟松的博客</div><div class="follow-button"><a target="_blank" rel="noopener" href="https://gitee.com/cheng_song">Gitee</a></div><hr><div class="author-info-articles"><a class="author-info-articles__archives article-meta" href="/archives"><span class="pull-left">文章</span><span class="pull-right">52</span></a><a class="author-info-articles__tags article-meta" href="/tags"><span class="pull-left">标签</span><span class="pull-right">45</span></a></div></div></div><div id="content-outer"><div id="top-container" style="background-image: url(/img/blog-bg.jpg)"><div id="page-header"><span class="pull-left"> <a id="site-name" href="/">晟松</a></span><i class="fa fa-bars toggle-menu pull-right" aria-hidden="true"></i><span class="pull-right menus">   <a class="site-page" href="/">Home</a><a class="site-page" href="/archives">Archives</a><a class="site-page" href="/tags">Tags</a><a class="site-page" href="/categories">Categories</a></span><span class="pull-right"><a class="site-page social-icon search"><i class="fa fa-search"></i><span> 搜索</span></a></span></div><div id="post-info"><div id="post-title">js各种知识</div><div id="post-meta"><time class="post-meta__date"><i class="fa fa-calendar" aria-hidden="true"></i> 2020-09-30</time><div class="post-meta-wordcount"><span>字数总计: </span><span class="word-count">9.7k</span><span class="post-meta__separator">|</span><span>阅读时长: 34 分钟</span></div></div></div></div><div class="layout" id="content-inner"><article id="post"><div class="article-container" id="post-content"><p>就是对一些js比较高级一点的知识的简单提及，现在可能会包括其他各种各样的前端碰见的问题和方法了</p>
<h2 id="各种杂乱知识点"><a href="#各种杂乱知识点" class="headerlink" title="各种杂乱知识点"></a>各种杂乱知识点</h2><h3 id="1-变量提升"><a href="#1-变量提升" class="headerlink" title="1.变量提升"></a>1.变量提升</h3><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/nokiaguy/article/details/106073431">参考一道题</a></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">10</span>;    </span><br><span class="line">&#123;              </span><br><span class="line">    a = <span class="number">99</span>;    <span class="comment">// 提升作用域，将a的值设为99，在这时还没有局部函数a呢！</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>) </span>&#123;   </span><br><span class="line">    &#125;</span><br><span class="line">    a = <span class="number">30</span>;       <span class="comment">// 实际上替换的是局部函数a</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(a);	<span class="comment">//非严格模式下，输出99</span></span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">10</span>;                   <span class="comment">//  定义顶层变量a</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">hello</span>(<span class="params"></span>) </span>&#123;        <span class="comment">// 提升到顶级作用域        </span></span><br><span class="line">        a = <span class="number">99</span>;               <span class="comment">// 如果是非执行级代码块，会优先考虑局部同名符号，如局部函数a，因此，这里实际上覆盖的是函数a，而不是全局变量10</span></span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>) </span>&#123;        <span class="comment">// 在非执行级代码块中，只在第1遍扫描中处理内嵌函数，第2遍扫描不处理，所以这是函数a已经被a=99覆盖了</span></span><br><span class="line">        &#125;                               </span><br><span class="line">        a = <span class="number">30</span>;               <span class="comment">// 覆盖a = 99   在hello函数内部，a的最终值是30</span></span><br><span class="line">    &#125;                        </span><br><span class="line">    hello();                 <span class="comment">// 执行</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(a);              <span class="comment">//  输出10</span></span><br></pre></td></tr></table></figure>

<p>var是函数作用域（包含它的函数的局部变量），let是块级作用域（类似一个大括号里面的作用域包括if，while，function等）。</p>
<p>使用var时，会自动将声明提升到函数的顶部，如果在全局里面声明的，就提升到全局的顶部，而且只是对声明进行提升，实际上的赋值还是在原来的地方，所以可以看见var的多次声明一个变量并赋值，其实只是声明了一次，后面都是赋值。但let就不会进行提升，所以不能重复声明同一变量，也不能在定义之前进行使用。</p>
<p>对于函数定义，还有<strong>函数声明提升</strong>，类似于var。但函数表达式就不可以了</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//函数声明</span></span><br><span class="line">consolo.log(sum(<span class="number">10</span>))</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">num</span>)</span>&#123;<span class="keyword">return</span> num&#125;</span><br><span class="line"><span class="comment">//函数表达式，在之前调用会error，而且不是let的原因</span></span><br><span class="line"><span class="keyword">let</span> sum = <span class="function"><span class="keyword">function</span>(<span class="params">num</span>)</span>&#123;<span class="keyword">return</span> num&#125;;</span><br><span class="line"><span class="comment">//除此之外，这两种方式等价</span></span><br></pre></td></tr></table></figure>



<h3 id="2-堆栈，深拷贝，浅拷贝"><a href="#2-堆栈，深拷贝，浅拷贝" class="headerlink" title="2.堆栈，深拷贝，浅拷贝"></a>2.堆栈，深拷贝，浅拷贝</h3><p><a target="_blank" rel="noopener" href="https://biaochenxuying.cn/articleDetail?article_id=5d1b1e2cb9e26b1e10d2e5d5">参考文章</a></p>
<p><strong>堆</strong>其实是一种特殊的树。只要满足这两点，它就是一个堆。</p>
<ul>
<li>堆是一个完全二叉树。 完全二叉树：除了最后一层，其他层的节点个数都是满的，最后一层的节点都靠左排列。</li>
<li>堆中每一个节点的值都必须大于等于（或小于等于）其子树中每个节点的值。 也可以说：堆中每个节点的值都大于等于（或者小于等于）其左右子节点的值。这两种表述是等价的。</li>
</ul>
<p>对于数据存储：</p>
<ul>
<li><strong>基本类型</strong>是保存在栈内存中的简单数据段，它们的值都有固定的大小，保存在栈空间，通过按值访问，并由系统自动分配和自动释放。 这样带来的好处就是，内存可以及时得到回收，相对于堆来说，更加容易管理内存空间。 JavaScript 中的 <code>Boolean、Null、Undefined、Number、String、Symbol</code> 都是基本类型。</li>
<li><strong>引用类型</strong>（如对象、数组、函数等）是保存在堆内存中的对象，值大小不固定，栈内存中存放的该对象的访问地址指向堆内存中的对象，JavaScript 不允许直接访问堆内存中的位置，因此操作对象时，实际操作对象的引用。 JavaScript 中的 <code>Object、Array、Function、RegExp、Date</code> 是引用类型。为什么引用类型要存在堆里面，是为了加快运算的速度</li>
</ul>
<p>在计算机的数据结构中，栈比堆的运算速度快，Object是一个复杂的结构且可以扩展：数组可扩充，对象可添加属性，都可以增删改查。将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。所以查找引用类型值的时候先去<strong>栈</strong>查找再去<strong>堆</strong>查找</p>
<p>深拷贝：复制得到的访问地址指向<code>不同的内存空间，互不相干</code>。所以修改其中一个值，另外一个不会改变。</p>
<p>平时使用数组复制时，我们大多数会使用 <code>=</code>，这只是浅拷贝，存在很多问题，会相互影响</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"><span class="keyword">let</span> arr2 = arr;<span class="comment">//或arr2 = Object.assign(arr)</span></span><br><span class="line"><span class="built_in">console</span>.log(arr) <span class="comment">//[1, 2, 3, 4, 5]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr2) <span class="comment">//[1, 2, 3, 4, 5]</span></span><br><span class="line">arr[<span class="number">0</span>] = <span class="number">6</span>;</span><br><span class="line"><span class="built_in">console</span>.log(arr) <span class="comment">//[6, 2, 3, 4, 5]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr2) <span class="comment">//[6, 2, 3, 4, 5]</span></span><br><span class="line">arr2[<span class="number">4</span>] = <span class="number">7</span>;</span><br><span class="line"><span class="built_in">console</span>.log(arr) <span class="comment">//[6, 2, 3, 4, 7]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr2) <span class="comment">//[6, 2, 3, 4, 7]</span></span><br></pre></td></tr></table></figure>

<p><strong>深拷贝的的复制过程</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> a = &#123; <span class="attr">x</span>: <span class="number">10</span>, <span class="attr">y</span>: <span class="number">20</span> &#125;</span><br><span class="line"><span class="comment">//先转换成字符类型，再转成object类型，成功在堆里面生成了一个新的对象数据，但是在这是一个function对象的时候就会发生错误</span></span><br><span class="line"><span class="keyword">let</span> b = <span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(a));</span><br><span class="line">b.x = <span class="number">5</span>;</span><br><span class="line"><span class="built_in">console</span>.log(a.x); <span class="comment">// 10</span></span><br><span class="line"><span class="built_in">console</span>.log(b.x); <span class="comment">// 5</span></span><br></pre></td></tr></table></figure>

<p>在原文章中还有一些对数组这些的一些方法（如slice，concat）的测试，实现深拷贝</p>
<h3 id="3-各种遇见的小技巧"><a href="#3-各种遇见的小技巧" class="headerlink" title="3.各种遇见的小技巧"></a>3.各种遇见的小技巧</h3><h4 id="取得两个值的中间值"><a href="#取得两个值的中间值" class="headerlink" title="取得两个值的中间值"></a>取得两个值的中间值</h4><p>因为有可能两个值之间相加可能会超出表示范围，虽然一般使用了bigint之后，不太可能会这样，但还是注意一下</p>
<p>使用    left+Math.floor( (right-left)/2 )</p>
<h4 id="随机数的生成"><a href="#随机数的生成" class="headerlink" title="随机数的生成"></a>随机数的生成</h4><p>Math.floor( random* (m-n +1) + n) )    包含n，也包含m</p>
<p>或者封装成一个函数进行调用</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">number = <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * total_number_of_choices + first_possible_value)</span><br><span class="line"><span class="comment">// 取随机数</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">selectRandomFrom</span>(<span class="params">lowerValue, upperValue</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">let</span> choices = upperValue - lowerValue + <span class="number">1</span>; </span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * choices + lowerValue); </span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">let</span> num = selectRandomFrom(<span class="number">2</span>,<span class="number">10</span>); </span><br><span class="line"><span class="built_in">console</span>.log(num); <span class="comment">// 2~10 范围内的值，其中包含 2 和 10</span></span><br></pre></td></tr></table></figure>



<h4 id="koa-class写controller"><a href="#koa-class写controller" class="headerlink" title="koa class写controller"></a><a target="_blank" rel="noopener" href="https://gitee.com/gfzl-open-source/vue-koa2#http://sinn.boyagirl.com/detail/58d9072cc1a5bd0001672cdc">koa class写controller</a></h4><p>class+async/await的结合，可以使得我们更好的组织api的逻辑层，语义和结构都会更加清晰。这样做就不用写一个逻辑处理函数都exports一次。直接暴露一个class出去就可以了。async函数作为class的静态方法,所有我们可以直接className.[xxx]来访问这些控制器。</p>
<p>先上代码:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"># 逻辑层（来自server/controllers/article.js）</span><br><span class="line"><span class="keyword">const</span> Article = <span class="built_in">require</span>(<span class="string">&#x27;../models/article.js&#x27;</span>);</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ArticleController</span></span>&#123;</span><br><span class="line">    <span class="comment">//创建文章</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">async</span> <span class="function"><span class="title">createArticle</span>(<span class="params">ctx, next</span>)</span>&#123;...&#125;</span><br><span class="line">    <span class="comment">//发布文章</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">async</span> <span class="function"><span class="title">ifPublishArticle</span>(<span class="params">ctx</span>)</span>&#123;...&#125;</span><br><span class="line">    <span class="comment">//获取所有文章</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">async</span> <span class="function"><span class="title">getAllArticles</span>(<span class="params">ctx</span>)</span>&#123;...&#125;</span><br><span class="line">    <span class="comment">//获取所以已发布的文章</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">async</span> <span class="function"><span class="title">getAllPublishedArticles</span>(<span class="params">ctx</span>)</span>&#123;...&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">exports</span> = <span class="built_in">module</span>.exports = ArticleController;</span><br><span class="line">                                     </span><br><span class="line"># 接口层(来自server/routes/index.js)</span><br><span class="line"><span class="comment">//引入class这个类</span></span><br><span class="line"><span class="keyword">const</span> A = <span class="built_in">require</span>(<span class="string">&#x27;../controllers/article.js&#x27;</span>);</span><br><span class="line">router</span><br><span class="line">    .get(<span class="string">&#x27;/articles/:id&#x27;</span>, A.getArticleById)                      </span><br><span class="line">    .post(<span class="string">&#x27;/articles&#x27;</span>, checkToken, A.createArticle)  </span><br></pre></td></tr></table></figure>



<h4 id="object原型判断数据类型"><a href="#object原型判断数据类型" class="headerlink" title="object原型判断数据类型"></a><a target="_blank" rel="noopener" href="https://www.cnblogs.com/bq-med/p/8796836.html">object原型判断数据类型</a></h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> arr=[<span class="number">1</span>,<span class="number">2</span>];</span><br><span class="line"></span><br><span class="line"><span class="comment">//直接对一个数组调用toString()</span></span><br><span class="line">arr.toString();<span class="comment">// &quot;1,2&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//通过call指定arr数组为Object.prototype对象中的toString方法的上下文</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(arr); <span class="comment">//&quot;[object Array]&quot;</span></span><br></pre></td></tr></table></figure>

<p>原理：当我们使用<code>arr.toString()</code>时，不能进行复杂数据类型的判断，因为它调用的是<code>Array.prototype.toString</code>，虽然<code>Array</code>也继承自<code>Object</code>，但js在<code>Array.prototype</code>上重写了<code>toString</code>，而我们通过<code>toString.call(arr)</code>实际上是通过原型链调用了<code>Object.prototype.toString</code>。</p>
<h3 id="4-各种小知识点"><a href="#4-各种小知识点" class="headerlink" title="4.各种小知识点"></a>4.各种小知识点</h3><h4 id="1：CommonJS-规范总结与扩展"><a href="#1：CommonJS-规范总结与扩展" class="headerlink" title="1：CommonJS 规范总结与扩展"></a>1：<a target="_blank" rel="noopener" href="https://github.com/sisterAn/blog/issues/4">CommonJS 规范总结与扩展</a></h4><p>前后端 JS 分别搁置在 HTTP 的两端，它们扮演的角色不同，侧重点也不一样。 浏览器端的 JS 需要经历从一个服务器端分发到多个客户端执行，而服务器端 JS 则是相同的代码需要多次执行。前者的瓶颈在于宽带，后者的瓶颈则在于 CPU 等内存资源。前者需要通过网络加载代码，后者则需要从磁盘中加载， 两者的加载速度也不是在一个数量级上的。<br>纵观 Node 的模块引入过程，几乎全都是同步的，尽管与 Node 强调异步的行为有些相反，但它是合理的，但前端如果也用同步方式引入，试想一下，在 UI 加载的过程中需要花费很多时间来等待脚本加载完成，这会造成用户体验的很大问题。</p>
<p>CommonJS 为后端 JS 制定的；     AMD（异步模块定义），ES6模块化（<code>export</code>和<code>import</code>）是 JS 前端的规范。</p>
<p><code>CommonJS</code>和ES6中模块化的两者区别</p>
<ul>
<li>前者支持动态导入，也就是 <code>require($&#123;path&#125;/xx.js)</code>，后者目前不支持，但是已有提案</li>
<li>前者是同步导入，因为用于服务端，文件都在本地，同步导入即使卡住主线程影响也不大。而后者是异步导入，因为用于浏览器，需要下载文件，如果也采用同步导入会对渲染有很大影响</li>
<li>前者在导出时都是值拷贝，就算导出的值变了，导入的值也不会改变，所以如果想更新值，必须重新导入一次。但是后者采用实时绑定的方式，导入导出的值都指向同一个内存地址，所以导入值会跟随导出值变化</li>
<li>后者会编译成 <code>require/exports</code> 来执行的</li>
</ul>
<h4 id="2：ES6的class使用"><a href="#2：ES6的class使用" class="headerlink" title="2：ES6的class使用"></a>2：<a target="_blank" rel="noopener" href="https://es6.ruanyifeng.com/#docs/class">ES6的class使用</a></h4><p>主要是在class定义的constructor中，在这里面定义的在this上面的变量才是实例变量，在constructor外面定义的变量和函数都是类本身的（也可称是在原型中）</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//定义类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Point</span> </span>&#123;</span><br><span class="line">  <span class="comment">//实例变量</span></span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">x, y</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.x = x;</span><br><span class="line">    <span class="built_in">this</span>.y = y;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="title">toString</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;(&#x27;</span> + <span class="built_in">this</span>.x + <span class="string">&#x27;, &#x27;</span> + <span class="built_in">this</span>.y + <span class="string">&#x27;)&#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> point = <span class="keyword">new</span> Point(<span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line"></span><br><span class="line">point.toString() <span class="comment">// (2, 3)</span></span><br><span class="line"></span><br><span class="line">point.hasOwnProperty(<span class="string">&#x27;x&#x27;</span>) <span class="comment">// true</span></span><br><span class="line">point.hasOwnProperty(<span class="string">&#x27;y&#x27;</span>) <span class="comment">// true</span></span><br><span class="line">point.hasOwnProperty(<span class="string">&#x27;toString&#x27;</span>) <span class="comment">// false</span></span><br><span class="line">point.__proto__.hasOwnProperty(<span class="string">&#x27;toString&#x27;</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>



<h4 id="3：js单线程和异步"><a href="#3：js单线程和异步" class="headerlink" title="3：js单线程和异步"></a>3：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/zhengyufeng/p/10895895.html">js单线程和异步</a></h4><p><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1K4411D7Jb?t=664">B站视频</a></p>
<p><img src="https://img2018.cnblogs.com/blog/1681656/201905/1681656-20190521094010441-614833594.png" alt="img"></p>
<p>​    WebAPIs：浏览器为异步任务单独开辟的线程（服务JavaScript的，处理JavaScript的异步）</p>
<p>​    虚线那一块（看图）：堆（heap）和栈（stack）共同组成了js主线程（这个就是我们JavaScript的线程）</p>
<p>​    callback queue（最下面的那个长方形）：任务队列，里面放着各种事件，比如我们点击所触发的事件，浏览器会帮我们以任务的形式，把他放入任务队列中</p>
<p>​    event loop（那个转圈圈）：任务循环，又叫事件循环。</p>
<p><strong>流程：</strong></p>
<p>  当我们的程序运行时，执行我们JavaScript的主线程，堆（heap）和栈（stack）共同组成了JavaScript的主线程，函数的执行就是通过进栈和出栈实现的。比如图中有一个foo()函数，主线程把它推入栈中，在执行函数体时，发现还需要执行上面的那几个函数，所以又把这几个函数推入栈中，等到函数执行完，就让函数出栈。当栈中的函数需要异步的时候，主线程会把需要异步的部分推给WebAPIs（浏览器开辟的线程），由WebAPIs去执行。</p>
<p>  当所有函数都执行完毕后，所有的函数就都被推出了栈。这个时候，程序就会通过event loop（事件循环）去callback queue（任务队列）中寻找下一个任务推入栈中。而WebAPIs（浏览器开辟的线程）执行完主程序推给他的异步之后，将处理后的结果以事件的形式丢到callback queue（任务队列）中，这个事件就是我们写代码的时候的回调函数。而这个时候任务队列里的任务正在往栈（stack）中推，所以异步之后的事件也会被推到栈（stack）中执行，但这个时候他已经不在是异步的了而是同步的，JavaScript的主线程是可以执行的。由此无论是同步还是异步，所有的函数全部执行完毕。</p>
<p><strong>（event loop（事件循环）总是会循环的查找任务队列里是否还有任务，有就往栈（stack）中推）</strong></p>
<img src="https://img2018.cnblogs.com/blog/1681656/201906/1681656-20190602140133041-896205690.png" alt="img" style="zoom: 50%;" />

<p><a target="_blank" rel="noopener" href="https://github.com/biaochenxuying/blog/issues/64">promise async await过程</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/sisterAn/blog/issues/21">浏览器的Tasks、microtasks、 queues 和 schedules</a></p>
<p><strong>任务队列 分为<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/bfc3e319a96b">宏任务和微任务</a>：</strong></p>
<p>宏任务队列：<code>setTimeout，setInterval ，setImmediate，I/O ，UI rendering （浏览器渲染）</code><br>微任务队列：<code>process.nextTick（下一个事件轮询的时间点上执行），Promise callback，Object.observer， MutationObserver（监视 DOM 变动的接口）</code></p>
<p><strong>关键：</strong></p>
<ol>
<li>当前在调用栈 (call stack) 内的所有函数会被执行。当它们返回值的时候，会被从栈内弹出。</li>
<li>当调用栈是空的时，所有排队的微任务会一个接一个从微任务任务队列中弹出进入调用栈中，然后在调用栈中被执行！(微任务自己也能返回一个新的微任务，有效地创建无限的微任务循环 )</li>
<li>如果调用栈和微任务队列都是空的，事件循环会检查宏任务队列里是否还有任务。如果宏任务中还有任务，会从宏任务队列中弹出进入调用栈，被执行后会从调用栈中弹出！</li>
<li>宏任务每次只会执行一个，有种说法：同步代码也可以算在宏任务队列里面</li>
</ol>
<p>一般微任务是先于宏任务执行的</p>
<h4 id="4：js对象方法"><a href="#4：js对象方法" class="headerlink" title="4：js对象方法"></a>4：<a target="_blank" rel="noopener" href="https://www.w3school.com.cn/js/js_object_methods.asp">js对象方法</a></h4><p>类似于这样的一个对象里面有一个属性为一个function</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> group = &#123;</span><br><span class="line">    <span class="attr">title</span>: <span class="string">&quot;Our Group&quot;</span>,</span><br><span class="line">    <span class="attr">students</span>: [<span class="string">&quot;John&quot;</span>, <span class="string">&quot;Pete&quot;</span>, <span class="string">&quot;Alice&quot;</span>],</span><br><span class="line">    <span class="comment">//对象方法 </span></span><br><span class="line">    <span class="attr">show</span>: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="built_in">console</span>.log(<span class="string">&#x27;this is a object function&#x27;</span>)&#125;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">//主要是说这个，这个es6对其的简化，让其不在使用function关键字这些，例如vue里面的data()&#123; return &#123;&#125;&#125;就使用了简化写法</span></span><br><span class="line">    <span class="function"><span class="title">showList</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.students.forEach(</span><br><span class="line">          <span class="function"><span class="params">student</span> =&gt;</span> alert(<span class="built_in">this</span>.title + <span class="string">&#x27;: &#x27;</span> + student)</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<h4 id="5：formdata文件上传"><a href="#5：formdata文件上传" class="headerlink" title="5：formdata文件上传"></a>5：<a target="_blank" rel="noopener" href="https://blog.csdn.net/liuyalu_/article/details/105836451">formdata文件上传</a></h4><p>其实也是一个像key：value的类型</p>
<p>一般使用axios的post进行文件上传，这里使用vant组件库的文件上传作为例子，因为vant没有对文件上传进行封装，可以更清晰的了解一下上传的全过程</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//这里是vue里面的一个使用formdata传文件的方法</span></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="title">afterRead</span>(<span class="params">file</span>)</span> &#123;</span><br><span class="line">      <span class="keyword">let</span> formdata = <span class="keyword">new</span> FormData();</span><br><span class="line">      <span class="comment">//这里的file.file就是实际上传的文件内容（或许是二进制形式？）</span></span><br><span class="line">      formdata.append(<span class="string">&quot;file&quot;</span>, file.file);</span><br><span class="line">      formdata.append(<span class="string">&quot;cheng&quot;</span>, <span class="string">&quot;chengsong123456&quot;</span>);</span><br><span class="line">      <span class="keyword">let</span> res = <span class="keyword">await</span> axios(&#123;</span><br><span class="line">        <span class="attr">url</span>: <span class="string">&quot;url/uploadimg&quot;</span>,</span><br><span class="line">        <span class="attr">method</span>: <span class="string">&quot;post&quot;</span>,</span><br><span class="line">        <span class="comment">// 这里要更改一下请求头</span></span><br><span class="line">        <span class="attr">headers</span>: &#123; <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span> &#125;,</span><br><span class="line">        <span class="attr">data</span>: formdata</span><br><span class="line">      &#125;);</span><br><span class="line">      <span class="built_in">this</span>.data = res;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure>

<p>这里面的formdata有两个字段，一个是file，一个是cheng。第一个是一个上传的图片文件，第二个是一个字符串</p>
<p>这两个在node后端里面所处的位置也不一样，前面的file是直接在req里面，使用req.file就可以拿到（使用了multer中间件），而后面的字符串就在req.body里面了，需要使用req.body.cheng才能拿到，注意这里的req.body是使用了body-parser中间件的</p>
<img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20201213115607145.png" alt="image-20201213115607145" style="zoom: 80%;" />

<img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20201213120630601.png" alt="image-20201213120630601" style="zoom:80%;" />



<p>至于跟在url后面的query参数，想下面的id这种</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">http://localhost:3000/users/send?test=test&amp;id=21</span><br></pre></td></tr></table></figure>

<p>可以直接在req.query里面拿到全部的query参数</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//这是nodejs后端的一个接口代码</span></span><br><span class="line">router.post(<span class="string">&quot;/send&quot;</span>,upload,<span class="function"><span class="keyword">function</span>(<span class="params">req,res</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (req.body.cheng === <span class="literal">undefined</span> &amp;&amp; req.cheng == <span class="literal">undefined</span>) &#123;</span><br><span class="line">        res.send(&#123; <span class="attr">msg</span>: <span class="string">&quot;文件不能为空&quot;</span> &#125;);</span><br><span class="line">    &#125; <span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;req:&#x27;</span>,req)</span><br><span class="line">        <span class="keyword">let</span> data = req.body.cheng</span><br><span class="line">        <span class="keyword">let</span> file = req.file;</span><br><span class="line">        res.send(&#123;<span class="attr">msg</span>:data,<span class="attr">file</span>:file,<span class="attr">id</span>:req.query&#125;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>发送的数据为：</p>
<img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20201213120504718.png" alt="image-20201213120504718" style="zoom:80%;" />

<p>返回的数据为</p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">	<span class="attr">&quot;msg&quot;</span>: <span class="string">&quot;song123&quot;</span>,</span><br><span class="line">	<span class="attr">&quot;file&quot;</span>: &#123;</span><br><span class="line">		<span class="attr">&quot;fieldname&quot;</span>: <span class="string">&quot;file&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;originalname&quot;</span>: <span class="string">&quot;rcd.db&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;encoding&quot;</span>: <span class="string">&quot;7bit&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;mimetype&quot;</span>: <span class="string">&quot;application/octet-stream&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;destination&quot;</span>: <span class="string">&quot;./public/uploads/&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;filename&quot;</span>: <span class="string">&quot;ebe916462f40761bac5531a62815ab0a&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;path&quot;</span>: <span class="string">&quot;public\\uploads\\ebe916462f40761bac5531a62815ab0a&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;size&quot;</span>: <span class="number">3805</span></span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">&quot;id&quot;</span>: &#123;</span><br><span class="line">		<span class="attr">&quot;ts&quot;</span>: <span class="string">&quot;ds&quot;</span>,</span><br><span class="line">		<span class="attr">&quot;id&quot;</span>: <span class="string">&quot;21&quot;</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>





<h4 id="6：浏览器console-log"><a href="#6：浏览器console-log" class="headerlink" title="6：浏览器console.log"></a>6：<a target="_blank" rel="noopener" href="https://blog.csdn.net/Ideality_hunter/article/details/71633995?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control">浏览器console.log</a></h4><p>谷歌的浏览器内核在设计的时候为了对性能进行调优，防止因为过多的console.log影响到原来的程序的性能，所以console.log其实是异步的，只是在展开的时候对快照进行实时计算得到的，骑在右边会有一个小感叹号的图标进行提示（在nodejs里面console.log是同步的）</p>
<h4 id="7：css的-important"><a href="#7：css的-important" class="headerlink" title="7：css的 !important"></a>7：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/planetwithpig/p/11804355.html">css的 !important</a></h4><p>简单的说，这就是一个增加样式权重的，这里的权重表示的是在多个地方对同一个元素样式进行改变之后，最终会呈现出什么样式</p>
<p><strong>注意</strong>：这里的 <strong>!important</strong> 不是 <strong>z-index</strong> ，一个是样式优先级，一个是堆叠优先级</p>
<h4 id="8：css自定义属性"><a href="#8：css自定义属性" class="headerlink" title="8：css自定义属性"></a>8：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/cangqinglang/p/11384703.html">css自定义属性</a></h4><p><code>--*</code>来声明变量名，<code>var(--*)</code>来使用</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">--<span class="selector-tag">a</span></span><br><span class="line"></span><br><span class="line"><span class="attribute">margin</span>: <span class="built_in">var</span>(--a)</span><br></pre></td></tr></table></figure>



<h4 id="9：vue动态绑定样式的bug"><a href="#9：vue动态绑定样式的bug" class="headerlink" title="9：vue动态绑定样式的bug"></a>9：<a target="_blank" rel="noopener" href="https://www.bilibili.com/video/av926272235">vue动态绑定样式的bug</a></h4><p>因为vue对动态绑定样式的一些数据侦听延迟，会造成样式的判断条件改变了，但样式并没有同步更新，需要更新一下界面。所以为了解决这个问题，就需要我们自己来使用 <strong>vue.set</strong> 来自己强制将数据侦听，或者说将数据改变之后，使用 <strong>Object.assign</strong> 重新给这个数据赋值给自己，也可以解决这个问题</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="built_in">this</span>.obj= <span class="built_in">Object</span>.assign(&#123;&#125;, <span class="built_in">this</span>.obj, &#123; <span class="attr">a</span>: <span class="number">1</span>, <span class="attr">e</span>: <span class="number">2</span> &#125;)</span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/71b1807b1815">参考vue.set使用</a></p>
<h4 id="10：vue项目eslint和本地冲突"><a href="#10：vue项目eslint和本地冲突" class="headerlink" title="10：vue项目eslint和本地冲突"></a><a target="_blank" rel="noopener" href="https://www.cnblogs.com/webhmy/p/12060651.html">10：vue项目eslint和本地冲突</a></h4><p>就是当你创建了一个项目之后，或者下载了一个别人的项目之后，发现别人的eslint格式与你的有一些区别，有时候会报错</p>
<p>一般是因为Vetur是使用prettier进行格式化，因为自己vscode的prettier插件的配置不同，就会导致不同的结果</p>
<p>这个时候一般可以直接在项目根目录下面创建 <strong>.prettierrc.json</strong> 文件，写你的项目局部使用格式</p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">	<span class="attr">&quot;singleQuote&quot;</span>:<span class="literal">false</span>, 	<span class="comment">// 是否对string使用单引号</span></span><br><span class="line">	<span class="attr">&quot;semi&quot;</span>:<span class="literal">true</span>, <span class="comment">// 是否每行末尾都添加分号</span></span><br><span class="line">    <span class="attr">&quot;trailingComma&quot;</span>:<span class="string">&quot;none&quot;</span> <span class="comment">// 对象末尾属性是否添加逗号</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>还有一个 <strong>.eslintrc.js</strong> 里面存储一些局部eslint的使用格式，也可以在这里进行修改，使之不与本地发送冲突</p>
<h4 id="11：setTimeout-func-4-7"><a href="#11：setTimeout-func-4-7" class="headerlink" title="11：setTimeout(func,4.7)"></a>11：setTimeout(func,4.7)</h4><p>这一段代码</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="built_in">setTimeout</span>(func,<span class="number">0</span>)</span><br></pre></td></tr></table></figure>

<p>其实并不会一直的以0毫秒的时间进行执行，js会自动给其加一个间隔时间，这个时间大概是4.7ms</p>
<p>同时注意，如果settimeout的第一个函数参数带有括号，那就是一个立即执行函数，会直接返回结果，不会延时输出</p>
<h4 id="12：js事件循环原理"><a href="#12：js事件循环原理" class="headerlink" title="12：js事件循环原理"></a><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1K4411D7Jb?t=664">12：js事件循环原理</a></h4><img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210315182440827.png" alt="image-20210315182440827" style="zoom: 50%;" />

<p>这张图左边是js脚本的运行，中间的一个环是事件环，右边的是渲染任务。而渲染任务是需要在事件执行之后才能进行执行</p>
<p>记住一个函数 <a target="_blank" rel="noopener" href="https://www.jianshu.com/p/fa5512dfb4f5"><strong>requestAnimationFrame</strong></a> 会让动画更加的流畅</p>
<h4 id="13：vue-router的特殊用法"><a href="#13：vue-router的特殊用法" class="headerlink" title="13：vue-router的特殊用法"></a>13：vue-router的特殊用法</h4><p>一般的嵌套路由是这样的</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">path</span>: <span class="string">&quot;/components&quot;</span>,</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;Components&quot;</span>,</span><br><span class="line">    <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="keyword">import</span>(<span class="string">&quot;@/views/NavView/Components.vue&quot;</span>),</span><br><span class="line">    <span class="attr">redirect</span>: <span class="string">&quot;/components/button&quot;</span>,</span><br><span class="line">    <span class="attr">children</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">path</span>: <span class="string">&quot;button&quot;</span>,</span><br><span class="line">            <span class="attr">name</span>: <span class="string">&quot;Button&quot;</span>,</span><br><span class="line">            <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="keyword">import</span>(<span class="string">&quot;@/views/Button.vue&quot;</span>),</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">path</span>: <span class="string">&quot;icon&quot;</span>,</span><br><span class="line">            <span class="attr">name</span>: <span class="string">&quot;Icon&quot;</span>,</span><br><span class="line">            <span class="attr">component</span>: <span class="function">() =&gt;</span> <span class="keyword">import</span>(<span class="string">&quot;@/views/Icon.vue&quot;</span>),</span><br><span class="line">        &#125;,</span><br><span class="line">    ],</span><br><span class="line">&#125;,</span><br><span class="line">    </span><br><span class="line"><span class="comment">// 后面的页面路由</span></span><br><span class="line"><span class="regexp">/components/</span>button</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其&lt;router-view /&gt;是在Components.vue文件里面</span></span><br></pre></td></tr></table></figure>

<p>现在看见了一种新的方式</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">path</span>: <span class="string">&quot;/home&quot;</span>,</span><br><span class="line">    <span class="attr">component</span>: Home,</span><br><span class="line">    <span class="comment">// redirect: &quot;/welcome&quot;,</span></span><br><span class="line">    <span class="attr">children</span>: [</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/welcome&quot;</span>, <span class="attr">component</span>: Welcome &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/less&quot;</span>, <span class="attr">component</span>: Less &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/variable&quot;</span>, <span class="attr">component</span>: Variable &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/mixins&quot;</span>, <span class="attr">component</span>: Mixins &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/nestedRules&quot;</span>, <span class="attr">component</span>: NestedRules &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/operations&quot;</span>, <span class="attr">component</span>: operations &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/namespace&quot;</span>, <span class="attr">component</span>: Namespace &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">&quot;/important&quot;</span>, <span class="attr">component</span>: Important &#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;,</span><br><span class="line">    </span><br><span class="line"><span class="comment">// 后面的页面路由</span></span><br><span class="line">/less</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其&lt;router-view /&gt;是在Home.vue文件里面</span></span><br></pre></td></tr></table></figure>

<p>直接就通过 <strong>/</strong> 变为绝对地址，就不需要加上前面的那个 /home 的前缀了</p>
<h4 id="14：v-for和v-if不能同时使用"><a href="#14：v-for和v-if不能同时使用" class="headerlink" title="14：v-for和v-if不能同时使用"></a><a target="_blank" rel="noopener" href="https://hub.fastgit.org/febobo/web-interview/issues/7">14：v-for和v-if不能同时使用</a></h4><p>在2.x版本里面，v-for的优先级高于v-if，所以同时使用会带来性能损失，</p>
<p>但在3.x版本里，v-if的优先级高于v-for，所以v-if不能获取到v-for里面循环的值</p>
<h4 id="15：一道特殊的js题-连等"><a href="#15：一道特殊的js题-连等" class="headerlink" title="15：一道特殊的js题-连等"></a><a target="_blank" rel="noopener" href="https://www.cnblogs.com/xxcanghai/p/4998076.html">15：一道特殊的js题-连等</a></h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;<span class="attr">n</span>: <span class="number">1</span>&#125;;</span><br><span class="line"><span class="keyword">var</span> b = a;</span><br><span class="line">a.x = a = &#123;<span class="attr">n</span>: <span class="number">2</span>&#125;;</span><br><span class="line"></span><br><span class="line">a.x 	<span class="comment">// 这时 a.x 的值是多少	undefined</span></span><br><span class="line">b.x 	<span class="comment">// 这时 b.x 的值是多少	&#123;n:1,x:&#123;n:2&#125;&#125;</span></span><br></pre></td></tr></table></figure>



<h4 id="16：事件代理"><a href="#16：事件代理" class="headerlink" title="16：事件代理"></a><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_38128179/article/details/86293394">16：事件代理</a></h4><p>简单的说就是使用</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">document.addEventListener(&quot;click&quot;, function()&#123;&#125;)</span><br></pre></td></tr></table></figure>

<p>而不是 <strong>dom.onclick()</strong> 这种一个个的单独监听。</p>
<p>主要是解决有多个元素需要监听时的场景</p>
<h4 id="17：vue-router的history原生api"><a href="#17：vue-router的history原生api" class="headerlink" title="17：vue-router的history原生api"></a><a target="_blank" rel="noopener" href="https://blog.csdn.net/u012961419/article/details/107338085">17：vue-router的history原生api</a></h4><p>主要是通过 <strong>pushState replaceState两个方法</strong> 还有 <strong>监听popState事件</strong>实现history模式</p>
<p>还有一些 <strong>go（传入number，进入特定的历史记录里）     back forward（类似浏览器的后退前进按键）</strong></p>
<p>活动的历史记录项发生变化时，就会触发popstate事件</p>
<h4 id="18：postcss和scss等区别"><a href="#18：postcss和scss等区别" class="headerlink" title="18：postcss和scss等区别"></a><a target="_blank" rel="noopener" href="https://blog.csdn.net/JoeBlackzqq/article/details/98885880">18：postcss和scss等区别</a></h4><p>scss等css预处理语言给css添加了更多的逻辑性的东西，然后编译成正常的css文件</p>
<p>postcss是通过js来处理css，通过将css解析为ast，然后使用插件进行操作。</p>
<p>postcss和以处理scss处理之后的css，比如添加前缀等。两者可以混合使用，但postcss需要与webpack等进行配置</p>
<h4 id="19：promise-resolve-reject后的代码也会运行"><a href="#19：promise-resolve-reject后的代码也会运行" class="headerlink" title="19：promise resolve/reject后的代码也会运行"></a>19：promise resolve/reject后的代码也会运行</h4><h4 id="20：块级作用域里的function"><a href="#20：块级作用域里的function" class="headerlink" title="20：块级作用域里的function"></a><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1Y5411T7ZF/">20：块级作用域里的function</a></h4><p>块级作用域里的function也会提升，且会绑定到全局window上面</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">0</span>;</span><br><span class="line"><span class="built_in">console</span>.log(a, <span class="built_in">window</span>.a) <span class="comment">// 0,0</span></span><br><span class="line"><span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">	<span class="built_in">console</span>.log(a, <span class="built_in">window</span>.a) <span class="comment">// f,0</span></span><br><span class="line">	a = <span class="number">10</span>;</span><br><span class="line">	<span class="keyword">debugger</span>;</span><br><span class="line">	<span class="built_in">console</span>.log(a, <span class="built_in">window</span>.a); <span class="comment">// 10,0</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>) </span>&#123; &#125;</span><br><span class="line">	<span class="built_in">console</span>.log(a, <span class="built_in">window</span>.a) <span class="comment">// 10,10</span></span><br><span class="line">	a = <span class="number">20</span>;</span><br><span class="line">	<span class="built_in">console</span>.log(a, <span class="built_in">window</span>.a) <span class="comment">// 20,10</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(a, <span class="built_in">window</span>.a) <span class="comment">// 10,10</span></span><br></pre></td></tr></table></figure>



<h4 id="21：使用浏览器的style的特定属性判断浏览器型号"><a href="#21：使用浏览器的style的特定属性判断浏览器型号" class="headerlink" title="21：使用浏览器的style的特定属性判断浏览器型号"></a><a target="_blank" rel="noopener" href="https://gitee.com/-/ide/project/leofe/React-Cloud-Music/edit/master/-/src/utils/index.js">21：使用浏览器的style的特定属性判断浏览器型号</a></h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 使用 transform 属性判断浏览器厂商</span></span><br><span class="line"><span class="keyword">const</span> getVendor = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> elStyle = <span class="built_in">document</span>.createElement(<span class="string">&#x27;div&#x27;</span>).style</span><br><span class="line">  <span class="keyword">const</span> transformNames = &#123;</span><br><span class="line">    <span class="attr">webkit</span>: <span class="string">&#x27;webkitTransform&#x27;</span>,</span><br><span class="line">    <span class="attr">moz</span>: <span class="string">&#x27;mozTransform&#x27;</span>,</span><br><span class="line">    <span class="attr">o</span>: <span class="string">&#x27;oTransform&#x27;</span>,</span><br><span class="line">    <span class="attr">ms</span>: <span class="string">&#x27;msTransform&#x27;</span>,</span><br><span class="line">    <span class="attr">standard</span>: <span class="string">&#x27;transform&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> transformNames) &#123;</span><br><span class="line">    <span class="keyword">if</span>(elStyle[transformNames[key]] !== <span class="literal">undefined</span> ) &#123;</span><br><span class="line">      <span class="keyword">return</span> key</span><br><span class="line">    &#125; </span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="22：css画扇形"><a href="#22：css画扇形" class="headerlink" title="22：css画扇形"></a><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/134173303">22：css画扇形</a></h4><p>一种方式是底板为白色，使用border-radius:50%变为圆，然后使用absolute定位两个半圆使用来相切，后面切出来一个扇形，但一个问题就是这样的话，会有一个圆的边缘会出现，类似于border:1px solid red；这种样子</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.circle</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: red;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.sector1</span> &#123;</span><br><span class="line">    <span class="attribute">transform-origin</span>: <span class="number">50px</span> <span class="number">50px</span>;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">90deg</span>);</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">0px</span>;</span><br><span class="line">    <span class="attribute">left</span>: <span class="number">0px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">50px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="built_in">rgb</span>(<span class="number">74</span>, <span class="number">151</span>, <span class="number">126</span>);</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">50px</span> <span class="number">0px</span> <span class="number">0</span> <span class="number">50px</span>;</span><br><span class="line">&#125;</span><br><span class="line">// 还有一个半圆</span><br></pre></td></tr></table></figure>

<p>另一种方式是使用css的一个新的属性 <strong>conic-gradient</strong> 锥形渐变。另一个就是线性渐变。使用conic-gradient的话就是绕着一个中心点变换颜色。通过其本身的一些属性就能控制形成一个饼图。当然，让其中一部分为白色的话，就会变成一个扇形了。</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-tag">div</span>&#123;</span><br><span class="line">	<span class="attribute">width</span>:<span class="number">200px</span>;</span><br><span class="line">	<span class="attribute">height</span>:<span class="number">200px</span>;</span><br><span class="line">	<span class="attribute">border-radius</span>:<span class="number">50%</span>;</span><br><span class="line">    // blue <span class="number">0</span> <span class="number">50%</span>表示blue从这个锥心开始的<span class="number">0</span>-<span class="number">50%</span>是蓝色。</span><br><span class="line">    // black <span class="number">50%</span> <span class="number">70%</span>同理表示<span class="number">50%</span>-<span class="number">70%</span>是黑色</span><br><span class="line">    // 最后的那两个就是skyblue与white的圆锥渐变</span><br><span class="line">	<span class="attribute">background</span>: <span class="built_in">conic-gradient</span>(blue <span class="number">0</span> <span class="number">50%</span>, black <span class="number">50%</span> <span class="number">70%</span>, skyblue <span class="number">70%</span> <span class="number">90%</span>, white);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><img src="C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20210710103839175.png" alt="image-20210710103839175"></p>
<p>还有一些特殊的属性，比如 from xx at xx% xx%可以改变圆锥的中心点是多少</p>
<h4 id="23：node中使用import"><a href="#23：node中使用import" class="headerlink" title="23：node中使用import"></a><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_36554693/article/details/105683996">23：node中使用import</a></h4><p>这里需要使用 babel 来进行编译才可以执行：</p>
<p>yarn add babel-cli babel-preset-es2015 -D</p>
<p>然后再根目录添加一个新文件 .babelrc：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;presets&quot;: [&quot;es2015&quot;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>启动脚本配置如下：</p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;scripts&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;dev&quot;</span>: <span class="string">&quot;nodemon index.js --exec babel-node&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;prod&quot;</span>: <span class="string">&quot;babel-node index.js&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="24：js对象的for-in顺序"><a href="#24：js对象的for-in顺序" class="headerlink" title="24：js对象的for in顺序"></a>24：js对象的for in顺序</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> map = &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> sy = <span class="built_in">Symbol</span>(<span class="number">2</span>);</span><br><span class="line">map[sy] = <span class="number">43</span>;</span><br><span class="line">map[<span class="number">2</span>] = <span class="number">43</span>;</span><br><span class="line">map[<span class="number">1</span>] = <span class="number">32</span>;</span><br><span class="line">map[<span class="number">12</span>] = <span class="number">4323</span>;</span><br><span class="line"></span><br><span class="line">map.b = <span class="number">43</span>;</span><br><span class="line">map.ab = <span class="number">43</span>;</span><br><span class="line">map.a = <span class="string">&quot;32&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;map: &quot;</span>, map);</span><br><span class="line"></span><br><span class="line">map:  &#123;</span><br><span class="line">  <span class="string">&#x27;1&#x27;</span>: <span class="number">32</span>,</span><br><span class="line">  <span class="string">&#x27;2&#x27;</span>: <span class="number">43</span>,</span><br><span class="line">  <span class="string">&#x27;12&#x27;</span>: <span class="number">4323</span>,</span><br><span class="line">  <span class="attr">b</span>: <span class="number">43</span>,</span><br><span class="line">  <span class="attr">ab</span>: <span class="number">43</span>,</span><br><span class="line">  <span class="attr">a</span>: <span class="string">&#x27;32&#x27;</span>,</span><br><span class="line">  [<span class="built_in">Symbol</span>(<span class="number">2</span>)]: <span class="number">43</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>先是数字（会排序），然后字符（按加入顺序），然后symbol这些，而使用 new Map()，就会是一个按加入的顺序遍历出来</p>
<h4 id="25：a–的问题"><a href="#25：a–的问题" class="headerlink" title="25：a–的问题"></a>25：a–的问题</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">3</span>;</span><br><span class="line"><span class="keyword">while</span> (a--) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(a);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 2 1 0</span></span><br><span class="line"></span><br><span class="line">a = <span class="number">3</span>;</span><br><span class="line"><span class="keyword">while</span> (a) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(a);</span><br><span class="line">    <span class="comment">// 注意这个a--需要放在这里，而不是在循环条件里面，不然在一次循环的时候，a在访问过后，还会进行一次 自减操作 ，</span></span><br><span class="line">        <span class="comment">// 使得循环里面的a出现问题，使得后面的判断不准确，详见下面的示例</span></span><br><span class="line">    a--;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 3 2 1</span></span><br></pre></td></tr></table></figure>

<p>虽然次数是不变的，但是在对立面具体的数字进行判断时，会出现一些问题</p>
<h2 id="书籍"><a href="#书籍" class="headerlink" title="书籍"></a>书籍</h2><h3 id="js高级程序设计（第四版）"><a href="#js高级程序设计（第四版）" class="headerlink" title="js高级程序设计（第四版）"></a>js高级程序设计（第四版）</h3><p>p236    实例只有指向原型的指针，没有指向构造函数的指针</p>
<p>p237    原型的问题还是源自其自身的共享特性，当原型上面存在引用类型（如数组）的时候，这个引用类型是共享的。当一个实例修改了这个数组，其他实例也能得到这个数组，一般而言，每个实例应该有自身的属性副本。</p>
<p>可使用<code>盗用构造函数（在子类构造函数中使用call()或apply()调用父类构造函数）</code>和**组合继承(主流)**（结合原型链和盗用构造函数，两者都使用）解决</p>
<p>p240    默认情况下，所有引用类型都继承自Object</p>
<p>p284    代理进行对赋值操作的属性检验</p>
<p>p289    因为函数名是指向函数的指针，所以一个函数可以有多个名称</p>
<p>p300    function定义的函数里面的this引用的是这个函数被调用时所处的作用域，而箭头函数就只是被<strong>定义</strong>时的上下文</p>
<p>p352    await关键字只能直接出现在异步函数的定义中</p>
<p>p467    css属性名使用连字符表示法，所以就算使用的时候必须将其转为驼峰命名</p>
<h3 id="你所不知道的js–上"><a href="#你所不知道的js–上" class="headerlink" title="你所不知道的js–上"></a>你所不知道的js–上</h3><p>感觉这一个系列的三本书有些久远了，都是15年的了，有一些跟不上现在的发展，所以简单看下就好，不必深究</p>
<p><strong>解析/语法分析（Parsing）</strong> </p>
<p>这个过程是将词法单元流（数组）转换成一个由元素逐级嵌套所组成的代表了程序语法 结构的树。这个树被称为“抽象语法树”（Abstract Syntax Tree，AST）。</p>
<p>eval(..) 函数可以接受一个字符串为参数，并将其中的内容视为好像在书 写时就存在于程序中这个位置的代码。换句话说，可以在你写的代码中用程序生成代码并运行，就好像代码是写在那个位置的一样</p>
<p>要避免书写eval和with这两个语法，因为会影响js引擎的编译性能</p>
<p>函数作用域的含义是指，属于这个函数的全部变量都可以在整个函数的范围内使用及复 用（事实上在嵌套的作用域中也可以使用）。</p>
<p><strong>闭包</strong></p>
<p>本质上无论何时何地，如果将函数（访问它们各自的词法作用域）当作第一级的值类型并到处传递，你就会看到闭包在这些函数中的应用。在定时器、事件监听器、 Ajax 请求、跨窗口通信、Web Workers 或者任何其他的异步（或者同步）任务中，只要使 用了回调函数，实际上就是在使用闭包！</p>
<p>理解闭包的关键在于：外部函数调用之后其变量对象本应该被销毁，但闭包的存在使我们仍然可以访问外部函数的变量对象，这就是闭包的重要概念</p>
<p>闭包有3个特性：</p>
<p>①函数嵌套函数</p>
<p>②函数内部可以引用函数外部的参数和变量</p>
<p>③参数和变量不会被垃圾回收机制回收 </p>
<p>P48 在循环里面的settimeout函数里面定义的函数的作用域解释</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//其实直接用let就行，但需要明白后面的原理</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">1</span>; i&lt;=<span class="number">5</span>; i++) &#123; </span><br><span class="line">	<span class="built_in">setTimeout</span>( <span class="function"><span class="keyword">function</span> <span class="title">timer</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line">		<span class="built_in">console</span>.log( i ); </span><br><span class="line">	&#125;, i*<span class="number">1000</span> ); </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//结果是：会以每秒一次的频率输出五次 6。这就是作用域的使用不当，js是单线程的，所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行，而在等待过程中for循环就已经在执行，等到setTimeout可以执行的时候，for循环已经结束，i的值也已经编程5</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//改进</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i=<span class="number">1</span>; i&lt;=<span class="number">5</span>; i++) &#123; </span><br><span class="line">    (<span class="function"><span class="keyword">function</span>(<span class="params">j</span>) </span>&#123; </span><br><span class="line">        <span class="built_in">setTimeout</span>( <span class="function"><span class="keyword">function</span> <span class="title">timer</span>(<span class="params"></span>) </span>&#123; <span class="built_in">console</span>.log( j ); &#125;, j*<span class="number">1000</span> );</span><br><span class="line">    &#125;)( i ); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>for 循环头部的 let 声明还会有一 个特殊的行为。这个行为指出变量在循环过程中不止被声明一次，每次迭代都会声明。随 后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。</p>
<p>简单来说闭包实则是词法作用域的产物；一个函数只要是在内部函数访问到外部函数的作用域我们则可以称之为<code>闭包</code></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//这也是一个闭包</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">var</span> a = <span class="string">&#x27;out var&#x27;</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(a);</span><br><span class="line">    &#125;</span><br><span class="line">    bar();</span><br><span class="line">&#125; </span><br><span class="line">foo();</span><br></pre></td></tr></table></figure>

<p>对于闭包，更常见的方式应该是<strong>模块模式</strong>，模块里面运行定义私有的实现（函数，变量 ），同时也可以暴露一些方法作为公开的API</p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1625874168103299234&wfr=spider&for=pc">参考</a></p>
<p><a target="_blank" rel="noopener" href="https://zh.javascript.info/closure">参考2</a></p>
<hr>
<p><strong>this和原型</strong></p>
<p>this 是在运行时进行绑定的，并不是在编写时绑定，它的上下文取决于函数调 用时的各种条件。this 的绑定和函数声明的位置没有任何关系，只取决于函数的调用方式</p>
<p>函数的调用栈，绑定规则</p>
<p>就可以顺序应用下面这四条规则来判断 this 的绑定对象。 </p>
<ol>
<li><p>由 new 调用？绑定到新创建的对象。 </p>
</li>
<li><p>由 call 或者 apply（或者 bind）调用？绑定到指定的对象。 </p>
</li>
<li><p>由上下文对象调用？绑定到那个上下文对象。 </p>
</li>
<li><p>默认：在严格模式下绑定到 undefined，否则绑定到全局对象</p>
</li>
</ol>
<p>P115 [[PUT]] 和 [[GET]]是对对象的描述表示，而setter和getter是对对象单个属性值的表示</p>
<p>setter 会覆盖单个属性默认的 [[Put]]（也被称为赋值）操作</p>
<p>in 操作符可以检查容器内是否有某个值，但是它实际上检查的是某 个属性名是否存在。对于数组来说这个区别非常重要，<br><code>4 in [2, 4, 6] </code>的结 果并不是你期待的 True，因为 [2, 4, 6] 这个数组中包含的属性名是 0、1、 2，没有 4。</p>
<p>Object.keys(..) 会返回一个数组，包含所有可枚举属性，Object.getOwnPropertyNames(..) 会返回一个数组，包含所有属性，无论它们是否可枚举。 </p>
<p>in 和 hasOwnProperty(..) 的区别在于是否查找 [[Prototype]] 链(in会查找原型链)，然而，Object.keys(..) 和 Object.getOwnPropertyNames(..) 都只会找对象直接包含的属性</p>
<h3 id="你所不知道的js–中"><a href="#你所不知道的js–中" class="headerlink" title="你所不知道的js–中"></a>你所不知道的js–中</h3><p><strong>类型与语法</strong></p>
<p>JavaScript 中的变量是没有类型的，只有值才有。变量可以随时持有任何类型的值</p>
<p>变量在未持有值的时候为 undefined。此时 typeof 返回 “undefined”：</p>
<p>数组通过数字进行索引，但有趣的是它们也是对象，所以也可以包含字符串键值和属性（但这些并不计算在数组长度内）</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">a=[]</span><br><span class="line">a[<span class="number">0</span>] = <span class="number">1</span></span><br><span class="line">a[<span class="string">&#x27;bc&#x27;</span>] = <span class="number">2</span></span><br><span class="line">a.lenght <span class="comment">// 1</span></span><br><span class="line">a.bc <span class="comment">// 2</span></span><br><span class="line"><span class="comment">//注意这个点的强制转换</span></span><br><span class="line">a[<span class="string">&#x27;23&#x27;</span>] = <span class="number">23</span></span><br><span class="line">a.length <span class="comment">// 24</span></span><br></pre></td></tr></table></figure>

<p>• undefined 指从未赋值</p>
<p>• null 指曾赋过值，但是目前没有值</p>
<p>null 是一个特殊关键字，不是标识符，我们不能将其当作变量来使用和赋值。然而</p>
<p>undefined 却是一个标识符，可以被当作变量来使用和赋值。</p>
<p>由于 NaN 和自身不相等，所以必须使用 ES6 中的 Number.isNaN(..)</p>
<p>ES6 中新加入了一个工具方法 Object.is(..) 来判断两个值是否绝对相等，主要用于特殊的判断，如NAN和+0，-0，Infinity，-Infinity</p>
<p>以下这些是假值：</p>
<p>• undefined</p>
<p>• null</p>
<p>• false</p>
<p>• +0、-0 和 NaN</p>
<p>• “”</p>
<p>假值的布尔强制类型转换结果为 false。</p>
<p>从逻辑上说，假值列表以外的都应该是真值（truthy）。但 JavaScript 规范对此并没有明确定义，只是给出了一些示例，例如规定所有的对象都是真值，<strong>我们可以理解为假值列表以外的值都是真值</strong>。</p>
<p>例如：[],    {},    function(){}都是真值</p>
<img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20201107165428413.png" alt="image-20201107165428413" style="zoom: 80%;" />

<p>我们要对 == 两边的值认真推敲，以下两个原则可以让我们有效地避免出错。</p>
<p>• 如果两边的值中有 true 或者 false，千万不要使用 ==。</p>
<p>• 如果两边的值中有 []、”” 或者 0，尽量不要使用 ==。这时最好用 === 来避免不经意的强制类型转换。这两个原则可以让我们避开几乎所有强制类型转换的坑。</p>
<p>所以 == 和 === 选择哪一个取决于是否允许在相等比较中发生强制类型转换</p>
<p>语句都有一个结果值（statement completion value，undefined 也算），获得结果值最直接的方法是在浏览器开发控制台中输入语句，默认情况下控制台会显示<strong>所执行的最后一条语句的结果值</strong>。</p>
<p>如果在控制台中输入 var a = 42 会得到结果值 undefined，而非 42</p>
<p>换句话说，代码块的结果值就如同一个隐式的返回，即返回最后一个语句的结果值</p>
<p>delete 用来删除对象中的属性和数组中的单元</p>
<p><strong>JavaScript 中的 &amp;&amp; 和 || 运算符返回它们其中一个操作数的值，而非true 或 false</strong></p>
<ul>
<li><p>42 || ’b‘;     // 42</p>
</li>
<li><p>​    true || false &amp;&amp; false; // true</p>
</li>
<li><p>​    (true || false) &amp;&amp; false; // false</p>
</li>
<li><p>​    true || (false &amp;&amp; false); // true</p>
</li>
</ul>
<p>这说明 &amp;&amp; 运算符先于 || 执行，而且执行顺序并非我们所设想的从左到右。原因就在于运算符优先级</p>
<p>暂时性死区：指的是由于代码中的变量还没有初始化而不能被引用的情况，对此，最直观的例子是 ES6 规范中的 let 块作用域，另一个 TDZ 违规的例子是 ES6 中的参数默认值</p>
<p>{<br> a = 2; // ReferenceError!<br> let a;<br>}</p>
<p>异步函数的<strong>回调地狱</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//假设所有的函数都是异步回调函数，最后的运行顺序会是ABCDEF</span></span><br><span class="line">doA( <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; </span><br><span class="line"> doC(); </span><br><span class="line"> doD( <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; </span><br><span class="line"> doF(); </span><br><span class="line"> &#125; ) </span><br><span class="line"> doE(); </span><br><span class="line">&#125; ); </span><br><span class="line">doB();</span><br></pre></td></tr></table></figure>

<p>通过回调表达程序异步和管理并发的两个主要缺陷：缺乏顺序性和可信任性(控制反转)。</p>
<p><strong>PROMISE</strong></p>
<p>虽然之前也写过一些关于promise的文字，但现在还是为了加深记忆，再写一些吧</p>
<p><a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000017312249">一篇比较好的文章</a></p>
<p>注意异步<strong>任务队列</strong>这个东西，会决定异步代码和同步代码的运行顺序</p>
<p><strong>链式流</strong></p>
<p>如果向 Promise.resolve(..) 传递一个非 Promise、非 thenable 的立即值，就会得到一个用这个值填充的 promise</p>
<p>而如果向 Promise.resolve(..) 传递一个真正的 Promise，就只会返回同一个 promise.对传入的 thenable 则会展开。如果这个 thenable 展开得到一个拒绝状态，那么从 Promise.resolve(..) 返回的 Promise 实际上就是这同一个拒绝状态</p>
<p>reject(..) 不会像 resolve(..) 一 样 进 行 展 开。 如 果 向reject(..) 传入一个 Promise/thenable 值，它会把这个值原封不动地设置为</p>
<p>拒绝理由。后续的拒绝处理函数接收到的是你实际传给 reject(..) 的那个Promise/thenable，而不是其底层的立即值</p>
<p>Promise 链的一个最佳实践就是最后总以一个 catch(..) 结束</p>
<p>catch也会返回一个promise实例，并且是resolved状态。<code>throw new Error()</code>抛出错误变为rejected状态</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">var p = Promise.resolve( 21 ); </span><br><span class="line">p.then( function(v)&#123; </span><br><span class="line">console.log( v ); // 21 </span><br><span class="line">// 创建一个promise并将其返回</span><br><span class="line">return new Promise( function(resolve,reject)&#123; </span><br><span class="line">// 用值42填充</span><br><span class="line">    resolve( v  * 2 ); </span><br><span class="line">   	 &#125; ); </span><br><span class="line">    &#125; ) </span><br><span class="line">    .then( function(v)&#123; </span><br><span class="line">		console.log( v ); // 42 </span><br><span class="line">&#125; ); </span><br></pre></td></tr></table></figure>

<p>虽然我们把 42 封装到了返回的 promise 中，但它仍然会被展开并最终成为链接的 promise的决议，因此第二个 then(..) 得到的仍然是 42。如果我们向封装的 promise 引入异步，一切都仍然会同样工作</p>
<p><strong>Promise.all([promise1,promise2… ])</strong></p>
<p>同时执行两个或更多步骤（也就是“并行执行”）。它们的完成顺序并不重要，但是必须都要完成，才能继续进行其他步骤</p>
<p>Promise.all([ .. ]) 需要一个参数，是一个数组，通常由 Promise 实例组成，当然就算不是promise也行，因为其实里面的都会被resolve一次，确保得到一有个真正的promise。如果数组是空的，主 Promise 就会立即完成。</p>
<p>从 Promise.all([ .. ]) 调用返回的 promise 会收到一个完成消息。这是一个由所有传入 promise 的完成消息组成的<strong>数组，与指定的顺序一致（与完成顺序无关）</strong></p>
<p>Promise.all([ .. ]) 返回的主 promise 在且仅在所有的成员 promise 都完成后才会完成。如果这些 promise 中有任何一个被拒绝的话，主 Promise.all([ .. ])promise 就会立即被拒绝，并丢弃来自其他所有 promise 的全部结果。</p>
<p><strong>Promise.race([promise1,promise2…])</strong></p>
<p>与 Promise.all([ .. ]) 类似，一旦有任何一个 Promise 决议为完成，Promise.race([ .. ])就会完成；一旦有任何一个 Promise 决议为拒绝，它就会拒绝。但不能传递空数组，不然会被一直挂住，不会返回</p>
<p><strong>web worker</strong></p>
<p>在js中运行一个类似多线程的程序</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> w1 = <span class="keyword">new</span> Worker( <span class="string">&quot;http://some.url.1/mycoolworker.js&quot;</span> );</span><br></pre></td></tr></table></figure>

<p>注意是一个js文件，Worker 之间以及它们和主程序之间，不会共享任何作用域或资源，不会发生抢占，锁这些多线程的东西</p>
<p>Worker w1 对象是一个事件侦听者和触发者，可以通过订阅它来获得这个 Worker 发出的事件以及发送事件给这个 Worker</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//主线程侦听事件</span></span><br><span class="line">w1.addEventListener( <span class="string">&quot;message&quot;</span>, <span class="function"><span class="keyword">function</span>(<span class="params">evt</span>)</span>&#123; </span><br><span class="line"> <span class="comment">// evt.data </span></span><br><span class="line">&#125; );</span><br><span class="line"><span class="comment">//发送 &quot;message&quot; 事件给这个 Worker：</span></span><br><span class="line">w1.postMessage( <span class="string">&quot;something cool to say&quot;</span> );</span><br><span class="line"></span><br><span class="line"><span class="comment">//在这个 Worker 内部，收发消息是完全对称的：</span></span><br><span class="line"><span class="comment">// &quot;mycoolworker.js&quot; </span></span><br><span class="line">addEventListener( <span class="string">&quot;message&quot;</span>, <span class="function"><span class="keyword">function</span>(<span class="params">evt</span>)</span>&#123; </span><br><span class="line"> <span class="comment">// evt.data </span></span><br><span class="line">&#125; ); </span><br><span class="line">postMessage( <span class="string">&quot;a really cool reply&quot;</span> );</span><br></pre></td></tr></table></figure>

<p>要在创建 Worker 的程序中终止 Worker，可以调用 Worker 对象（就像前面代码中的 w1）上的 terminate()。突然终止 Worker 线程不会给它任何机会完成它的工作或者清理任何资源。这就类似于通过关闭浏览器标签页来关闭页面</p>
<p>Web Worker 通常应用于哪些方面呢？</p>
<ul>
<li> 处理密集型数学计算</li>
<li> 大数据集排序</li>
<li> 数据处理（压缩、音频分析、图像处理等）</li>
<li> 高流量网络通信</li>
</ul>
<p>具体的实现和操作，到时候看文档吧</p>
<h3 id="你所不知道的js–下"><a href="#你所不知道的js–下" class="headerlink" title="你所不知道的js–下"></a>你所不知道的js–下</h3><p>这本书感觉更像是上面两本书的一个简单总结，不打算对这本书进行记录</p>
</div></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">晟松</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://chengsong.info/2020/09/30/js各种知识/">https://chengsong.info/2020/09/30/js各种知识/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://chengsong.info">晟松</a>！</span></div></div><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/js-other/">js other</a></div><nav id="pagination"><div class="prev-post pull-left"><a href="/2020/10/12/leetcode%E8%AE%B0%E5%BD%95%E7%9A%84%E4%B8%80%E4%BA%9B%E9%A2%98/"><i class="fa fa-chevron-left">  </i><span>leetcode记录的一些题</span></a></div><div class="next-post pull-right"><a href="/2020/09/17/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/"><span>数据结构和算法</span><i class="fa fa-chevron-right"></i></a></div></nav></div></div><footer class="footer-bg" style="background-image: url(/img/blog-bg.jpg)"><div class="layout" id="footer"><div class="copyright">&copy;2020 - 2023 By 晟松</div><div class="framework-info"><span>驱动 - </span><a target="_blank" rel="noopener" href="http://hexo.io"><span>Hexo</span></a><span class="footer-separator">|</span><span>主题 - </span><a target="_blank" rel="noopener" href="https://github.com/Molunerfinn/hexo-theme-melody"><span>Melody</span></a></div><div class="icp"><a target="_blank" rel="noopener" href="http://www.beian.miit.gov.cn/"><span>湘ICP备2020021729号</span></a></div><div class="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_page_pv"><i class="fa fa-file"></i><span id="busuanzi_value_page_pv"></span><span></span></span></div></div></footer><i class="fa fa-arrow-up" id="go-up" aria-hidden="true"></i><script src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@latest/velocity.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-ui-pack@latest/velocity.ui.min.js"></script><script src="/js/utils.js?version=1.9.0"></script><script src="/js/fancybox.js?version=1.9.0"></script><script src="/js/sidebar.js?version=1.9.0"></script><script src="/js/copy.js?version=1.9.0"></script><script src="/js/fireworks.js?version=1.9.0"></script><script src="/js/transition.js?version=1.9.0"></script><script src="/js/scroll.js?version=1.9.0"></script><script src="/js/head.js?version=1.9.0"></script><script src="/js/search/local-search.js"></script><script>if(/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
  $('#nav').addClass('is-mobile')
  $('footer').addClass('is-mobile')
  $('#top-container').addClass('is-mobile')
}</script><div class="search-dialog" id="local-search"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章"></div></div></div><hr><div id="local-search-results"><div id="local-hits"></div><div id="local-stats"><div class="local-search-stats__hr" id="hr"><span>由</span> <a target="_blank" rel="noopener" href="https://github.com/wzpan/hexo-generator-search" style="color:#49B1F5;">hexo-generator-search</a>
 <span>提供支持</span></div></div></div><span class="search-close-button"><i class="fa fa-times"></i></span></div><div class="search-mask"></div></body></html>